from stat import S_IFDIR, S_IFREG, S_IREAD
from time import time
import os
from moodlefuse.settings import CACHE_FOLDER
from moodlefuse.fuse import fuse_get_context
import hashlib
import random
import shutil
from posixpath import basename

class FileState(object):
    CLEAN, DIRTY = range(2)

class FileSource(object):
    CREATED, DOWNLOADED = range(2)

class File(object):

    def __init__(self, api, name, url, **kwargs):
        self.api    = api
        self.name   = name
        self.url    = url

        """
        - st_mode (protection bits)
        - st_ino (inode number)
        - st_dev (device)
        - st_nlink (number of hard links)
        - st_uid (user ID of owner)
        - st_gid (group ID of owner)
        - st_size (size of file, in bytes)
        - st_atime (time of most recent access)
        - st_mtime (time of most recent content modification)
        - st_ctime (platform dependent; time of most recent metadata change on Unix,
                    or the time of creation on Windows).
        """
        uid, gid, pid = fuse_get_context()
        self.attrs = {
            'st_mode'   : (S_IFREG | 0755),
            'st_mtime'  : time(),
            'st_atime'  : time(),
            'st_nlink'  : 0,
            'st_uid'    : uid,
            'st_gid'    : gid,
            'st_size'   : 0
        }
        if 'attrs' in kwargs:
            self.attrs = dict(self.attrs, **kwargs['attrs'])

        if 'source' in kwargs:
            self.source = kwargs['source']
        else:
            self.source = FileSource.CREATED

        if 'state' in kwargs:
            self.state = kwargs['state']
        else:
            self.state = FileState.CLEAN

    def init(self, **kwargs):
        pass

    def __str__(self):
        return "%s - %s" % (self.__class__.__name__, self.name)

class RegularFile(File):

    def __init__(self, api, name, url, **kwargs):
        super(RegularFile, self).__init__(api, name, url, **kwargs)
        self.filepath = self.build_cache_filepath()

    def build_cache_filepath(self):
        hash = hashlib.md5()
        hash.update(self.name)
        hash.update(str(random.random()))
        
        return CACHE_FOLDER + hash.hexdigest()

    def create_cache_file(self):
        open(self.filepath, 'w+').close()

    def read(self, size, offset):
        if not os.path.exists(self.filepath):
            if self.source == FileSource.DOWNLOADED:
                self.attrs['st_size'] = self.api.read_raw_file(self.filepath, self.url)
            else:
                self.create_cache_file()

        with open(self.filepath, 'rb+') as file:
            file.seek(offset, 0)
            return file.read(size)

    def write(self, data, offset):
        with open(self.filepath, 'rb+') as file:
            file.seek(offset, 0)
            file.write(data)

        self.attrs['st_size'] += len(data)
        self.state = FileState.DIRTY

    def truncate(self, length):
        with open(self.filepath, 'rb+') as file:
            file.truncate(length)

        self.attrs['st_size'] = length
        self.state = FileState.DIRTY

    def rename(self, new_filepath):
        old_filepath = self.filepath

        self.name       = basename(new_filepath)
        self.filepath   = self.build_cache_filepath()

        shutil.copy(old_filepath, self.filepath)

        return self.name


    def sync(self):
        pass

class Directory(File):

    def __init__(self, api, name, url, **kwargs):
        super(Directory, self).__init__(api, name, url, **kwargs)
        
        self.files = {}
        self.is_synced = False

        self.attrs['st_mode'] = (S_IFDIR | S_IREAD)

    def load_files(self):
        pass

    def create_file(self, name, mode):
        pass

    def get_files(self):
        if not self.is_synced:
            self.load_files()
            self.is_synced = True

        return self.files